package com.atguigu.gmall.order.controller;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.cart.CartFeignClient;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.util.AuthContextHolder;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.user.UserAddress;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.user.client.UserFeignClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author mqx
 * @date 2020-10-22 10:47:15
 */
@RestController
@RequestMapping("api/order")
public class OrderApiController {

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private CartFeignClient cartFeignClient;

    @Autowired
    private OrderService orderService;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    //  定义远程接口
    @GetMapping("auth/trade")
    public Result trade(HttpServletRequest request){
        String userId = AuthContextHolder.getUserId(request);
        //  需要获取到用户Id
        //  第一件事：获取到收货人的地址列表
        List<UserAddress> userAddressList = userFeignClient.findUserAddressListByUserId(userId);
        //  第二件事：获取到用户购买的商品列表
        List<CartInfo> cartCheckedList = cartFeignClient.getCartCheckedList(userId);
        //  声明一个订单明细的集合，来存储数据
        List<OrderDetail> orderDetailList = new ArrayList<>();
        //  数据渲染时，应该渲染订单明细OrderDetail.
        for (CartInfo cartInfo : cartCheckedList) {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setSkuId(cartInfo.getSkuId());
            orderDetail.setSkuName(cartInfo.getSkuName());
            orderDetail.setImgUrl(cartInfo.getImgUrl());
            orderDetail.setSkuNum(cartInfo.getSkuNum());
            orderDetail.setOrderPrice(cartInfo.getSkuPrice());

            //  将每个orderDetail 放入集合
            orderDetailList.add(orderDetail);
        }

        //  页面需要总金额
        OrderInfo orderInfo = new OrderInfo();
        //  必须知道当前订单购买了哪些商品
        orderInfo.setOrderDetailList(orderDetailList);
        //  计算总金额
        orderInfo.sumTotalAmount();
        //  此处：跟商品详情做数据汇总一样！

        Map<String, Object> result = new HashMap<>();
        //  页面需要渲染，必须有key，此处存储的key 必须跟前台页面保存一致！
        result.put("userAddressList",userAddressList);
        result.put("detailArrayList",orderDetailList);
        //  件数：第一种理解,可以认为集合的长度，第二种：每个商品件数的总和。
        result.put("totalNum",orderDetailList.size());
        result.put("totalAmount",orderInfo.getTotalAmount());

        //  设置一个流水号
        String tradeNo = orderService.getTradeNo(userId);
        result.put("tradeNo",tradeNo);
        return  Result.ok(result);
    }

    // web-all , 返回页面。trade.html ,要数据 ，获取后台存储数据，requset.add("key", result.getData());
    // web-all , 返回页面。trade.html, 如果不需要code 等。那么我们也可以返回集合。


    //  http://api.gmall.com/api/order/auth/submitOrder?tradeNo=null
    //  保存控制器   tradeNo=null tradeNo是什么呢? 页面生产的流水号。
    //  页面提交过来的是Json 字符串 ，将其变为OrderInfo 对象。
    @PostMapping("auth/submitOrder")
    public Result submitOrder(@RequestBody OrderInfo orderInfo,HttpServletRequest request){

        //  获取用户Id
        String userId = AuthContextHolder.getUserId(request);
        //  【userId】
        orderInfo.setUserId(Long.parseLong(userId));

        //  在保存之前执行 http://api.gmall.com/api/order/auth/submitOrder?tradeNo=null
        //  获取到前台传递过来的流水号
        String tradeNo = request.getParameter("tradeNo");

        //  调用比较方法
        //  表示流水号不一致
        if(!orderService.checkTradeCode(tradeNo,userId)){
            //  提示消息
            return Result.fail().message("不能重复提交订单！");
        }

        //  删除
        orderService.delTradeNo(userId);

        //  验证库存： 需要每个商品都进行验证 
        //        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        //        for (OrderDetail orderDetail : orderDetailList) {
        //            //  远程调用验证
        //            boolean res = orderService.checkStock(orderDetail.getSkuId(), orderDetail.getSkuNum());
        //            //  res = true 表示有库存，fasle 表示库存不足
        //            if (!res){
        //                //  提示消息
        //                return Result.fail().message(orderDetail.getSkuName()+"库存不足！");
        //            }
        //
        //            //  在此验证价格：
        //            //  orderDetail.getOrderPrice() == 商品的实时价格 skuInfo.getPrice();
        //            //  获取实时价格
        //            BigDecimal skuPrice = productFeignClient.getSkuPrice(orderDetail.getSkuId());
        //            //  做对比
        //            if (orderDetail.getOrderPrice().compareTo(skuPrice)!=0){
        //                //  价格有变动，那么应该将原来的价格进行修改。
        //                //  购物车.loadCartCache();    将其放入feign-client 中。
        //                //  提示消息
        //                cartFeignClient.loadCartCache(userId);
        //                return Result.fail().message(orderDetail.getSkuName()+"价格有变动！");
        //            }
        //        }

        //  声明一个异步编排的集合，还需要一个获取每个CompletableFuture结果集的集合！
        //        List<CompletableFuture> completableFutureList = new ArrayList<>();
        //        completableFutureList.add(kuc);
        //        strList.add("msg");
        //        completableFutureList.add(price);
        //        strList.add("msg");
        //        //  List<String> strList = new ArrayList();
        //        CompletableFuture.supplyAsync();
        //        CompletableFuture.allOf()
        //        判断 strList 的长度
        //  使用异步编排来完成！
        //  获取CompletableFuture结果集的集合
        List<String> errorList = new ArrayList<>();
        //  声明一个异步编排的集合
        List<CompletableFuture> futureList = new ArrayList<>();
        //  表示获取订单明细
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            //  开启异步编排
            //  验证库存
            CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
                boolean res = orderService.checkStock(orderDetail.getSkuId(), orderDetail.getSkuNum());
                //  res = true 表示有库存，fasle 表示库存不足
                if (!res) {
                    //  提示消息
                    //  return Result.fail().message(orderDetail.getSkuName()+"库存不足！");
                    errorList.add(orderDetail.getSkuName() + "库存不足！");
                }
            }, threadPoolExecutor);
            //  将验证价格的线程添加到集合
            futureList.add(completableFuture);

            //  验证价格
            CompletableFuture<Void> priceCompletableFuture = CompletableFuture.runAsync(() -> {
                // 获取实时价格
                BigDecimal skuPrice = productFeignClient.getSkuPrice(orderDetail.getSkuId());
                //  做对比
                if (orderDetail.getOrderPrice().compareTo(skuPrice)!=0){
                    //  价格有变动，那么应该将原来的价格进行修改。
                    //  购物车.loadCartCache();    将其放入feign-client 中。
                    //  提示消息
                    cartFeignClient.loadCartCache(userId);
                    errorList.add(orderDetail.getSkuName()+"价格有变动！");
                }

            }, threadPoolExecutor);
            //  将验证价格的线程添加到集合
            futureList.add(priceCompletableFuture);
        }

        //  CompletableFuture 组合
        CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()])).join();

        //  判断结果：
        if (errorList.size()>0){
            //  说明有错误了！
            //            for (String s : errorList) {
            //                return Result.fail().message(s);
            //            }
        //  如果有价格变动，则提示价格变动。如果有库存不足，则需要提示库存不足！
        //  skuId29库存不足 ,价格有变动！
            return Result.fail().message(StringUtils.join(errorList, ","));
            //  alert("skuId29库存不足 ,价格有变动！")
            //  return Result.fail().message(errorList.get(0));
        }
        // 调用保存方法
        Long orderId = orderService.saveOrderInfo(orderInfo);

        return Result.ok(orderId);
    }


    @GetMapping("inner/getOrderInfo/{orderId}")
    public OrderInfo getOrderInfo(@PathVariable Long orderId){
        return orderService.getOrderInfo(orderId);
    }

    //  建立一个拆单控制器！  http://localhost:8204/api/order/orderSplit
    //  http://localhost:8204/api/order/orderSplit?orderId=xxx&wareSkuMap=xxx
    @RequestMapping("orderSplit")
    public String orderSplit (HttpServletRequest request){
        //  获取传递的参数：
        //  原始订单 ： 购买的商品 2，10，3 商品！
        String orderId = request.getParameter("orderId");
        //  [{"wareId":"1","skuIds":["2","10"]},{"wareId":"2","skuIds":["3"]}]
        String wareSkuMap = request.getParameter("wareSkuMap");

        //  调用服务层的拆单方法
        List<OrderInfo> subOrderInfoList =  orderService.orderSplit(Long.parseLong(orderId),wareSkuMap);
        //  声明一个集合
        ArrayList<Map> mapArrayList = new ArrayList<>();
        //  返回的是orderInfo 中的部分字段。
        if(!CollectionUtils.isEmpty(subOrderInfoList)){
            for (OrderInfo orderInfo : subOrderInfoList) {
                //  orderInfo 变成map
                Map map = orderService.initWareOrder(orderInfo);
                //  将map 添加到集合
                mapArrayList.add(map);
            }
        }
        //  返回子订单集合
        return JSON.toJSONString(mapArrayList);
    }

    //  秒杀的订单！
    @PostMapping("inner/seckill/submitOrder")
    public Long submitOrder(@RequestBody OrderInfo orderInfo){
        //  调用服务
        Long orderId = orderService.saveOrderInfo(orderInfo);
        return orderId;
    }
}
